home *** CD-ROM | disk | FTP | other *** search
/ Aminet 5 / Aminet 5 - March 1995.iso / Aminet / dev / misc / LEDA_src.lha / LEDA-3.1c-source / src / vga.old / _vgawin.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-17  |  24.6 KB  |  1,116 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  3.1c
  4. +
  5. +
  6. +  _vgawin.c
  7. +
  8. +
  9. +  Copyright (c) 1994  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15.  
  16. #include "vgalib.h"
  17.  
  18. /*----------------------------------------------------------------------------*/
  19. /* event handling, window manager, etc ...                                    */
  20. /*----------------------------------------------------------------------------*/
  21.  
  22. #define BORDER_W 5
  23. #define HEADER_W 20 
  24.  
  25. static int display = 0;
  26. static int mouse_installed=0;
  27. static int mouse_two_buttons=0;
  28.  
  29. static Window root_win = 0;
  30. static Window  win_stack[16];
  31. static int win_top = 0;
  32.  
  33. static int root_color = 14; // grey 
  34.  
  35. static int pointer_shape = 0;
  36. static int mouse_x = DISP_WIDTH/2;
  37. static int mouse_y = DISP_HEIGHT/2;
  38.  
  39. static int event_buffer_e = -1;
  40. static int event_buffer_val;
  41. static Window event_buffer_win;
  42.  
  43. static int last_event_e;
  44. static int last_event_val;
  45. static Window last_event_win;
  46.  
  47. static int pointer_visible = 0;
  48.  
  49. static int save_mode;
  50. static int save_lw;
  51. static int save_ls;
  52.  
  53.  
  54. static unsigned char pointer_mask[2][2][14] = { 
  55. {{0xc0,0xf0,0x7c,0x7f,0x3f,0x3f,0x1f,0x1f,0x0d,0x0c,0x00,0x00,0x00,0x00},
  56.  {0x00,0x00,0x00,0x00,0xc0,0xc0,0x00,0x80,0xc0,0xe0,0x70,0x38,0x1c,0x0c}},
  57.  
  58. {{0x00,0x00,0x00,0x00,0x03,0x03,0x00,0x01,0x03,0x07,0x0e,0x1c,0x38,0x30},
  59.  {0x03,0x0f,0x3e,0xfe,0xfc,0xfc,0xf8,0xf8,0xb0,0x30,0x00,0x00,0x00,0x00} }
  60. };
  61.  
  62.  
  63. static void draw_pointer()
  64. {
  65.   register int x1 = mouse_x % 8;
  66.   register int x2 = 8-x1;
  67.   register int x = mouse_x/8;
  68.   VIDEO_PTR start = VIDEO + LINE_BYTES*mouse_y + x;
  69.   register VIDEO_PTR q;
  70.   register unsigned char c;
  71.  
  72.   set_color(black);
  73.  
  74.   if (pointer_shape == 1)
  75.   { pixel(root_win,mouse_x-2,mouse_y);
  76.     pixel(root_win,mouse_x-1,mouse_y);
  77.     pixel(root_win,mouse_x,mouse_y);
  78.     pixel(root_win,mouse_x+1,mouse_y);
  79.     pixel(root_win,mouse_x+3,mouse_y);
  80.     pixel(root_win,mouse_x,mouse_y-2);
  81.     pixel(root_win,mouse_x,mouse_y-1);
  82.     pixel(root_win,mouse_x,mouse_y+1);
  83.     pixel(root_win,mouse_x,mouse_y+2);
  84.     circle(root_win,mouse_x,mouse_y,6);
  85.     return;
  86.    }
  87.  
  88.  
  89.   int a = 0;
  90.   int b = 14;
  91.   int d = 1;
  92.   int k = 0;
  93.  
  94.   if (mouse_y + 15 > DISP_MAX_Y) 
  95.   { a = 13;
  96.     b = -1;
  97.     d = -1;
  98.     start -= 14*LINE_BYTES;
  99.    }
  100.  
  101.   if (x > 77) 
  102.   { start -= 2;
  103.     k = 1;
  104.    }
  105.  
  106.   port_out(8, GRA_I);
  107.  
  108.   for(int i=a; i!=b; i+=d)
  109.   { q = start;
  110.     c = (pointer_mask[k][0][i]>>x1);
  111.     port_out(c, GRA_D);
  112.     *q = *q;
  113.     ++q; 
  114.     c = ((pointer_mask[k][1][i]>>x1) | (pointer_mask[k][0][i]<<x2));
  115.     port_out(c, GRA_D);
  116.     *q = *q;
  117.     
  118.     if (x2)
  119.     { ++q;
  120.       c = (pointer_mask[k][1][i]<<x2);
  121.       port_out(c, GRA_D);
  122.       *q = *q;
  123.      }
  124.     start+=LINE_BYTES;
  125.    }
  126. }
  127.  
  128. static void show_pointer()
  129. { if (!pointer_visible) draw_pointer(); 
  130.   pointer_visible = 1;
  131.  }
  132.  
  133. static void hide_pointer()
  134. { if (pointer_visible) draw_pointer(); 
  135.   pointer_visible = 0;
  136.  }
  137.  
  138.  
  139. static void set_pointer_shape(int shape)
  140. { if (pointer_shape != shape) 
  141.   { draw_pointer();
  142.     pointer_shape = shape;
  143.     draw_pointer();
  144.   }
  145.  }
  146.  
  147.  
  148. static void save_box(Window win)
  149. { register int y;
  150.   register VIDEO_PTR p;
  151.   register VIDEO_PTR q;
  152.   register VIDEO_PTR first;
  153.   register VIDEO_PTR last;
  154.  
  155.   if (win_top <= 1) { win->plane[0] = 0; return; }
  156.  
  157.   int left   = win->x0;
  158.   int top    = win->y0;
  159.   int right  = win->x1;
  160.   int bottom = win->y1;
  161.  
  162.   int i,l,r;
  163.  
  164.   if(left < 0) left = 0;
  165.   if(top  < 0) top = 0;
  166.   if(right  > DISP_MAX_X) right = DISP_MAX_X;
  167.   if(bottom > DISP_MAX_Y) bottom = DISP_MAX_Y;
  168.  
  169.   l = (left>>3);
  170.   r = (right>>3);
  171.  
  172.   win->plane[0] = (VIDEO_PTR)malloc((r-l+1)*(bottom-top+1));
  173.   win->plane[1] = (VIDEO_PTR)malloc((r-l+1)*(bottom-top+1));
  174.   win->plane[2] = (VIDEO_PTR)malloc((r-l+1)*(bottom-top+1));
  175.   win->plane[3] = (VIDEO_PTR)malloc((r-l+1)*(bottom-top+1));
  176.  
  177.   /* set read mode 0 */
  178.   port_out(5, GRA_I);
  179.   port_out(0, GRA_D);
  180.  
  181.   /* read planes 0 to 3 */
  182.   for(i=0; i<4; i++)
  183.   { p = win->plane[i];
  184.  
  185.     port_out(4, GRA_I);
  186.     port_out(i, GRA_D);
  187.  
  188.     first = VIDEO + LINE_BYTES*top + l;
  189.     last  = VIDEO + LINE_BYTES*top + r;
  190.  
  191.     for(y=top; y<=bottom; y++)
  192.     { for(q=first; q<=last; q++) *p++ = *q;
  193.       first  += LINE_BYTES;
  194.       last   += LINE_BYTES;
  195.      }
  196.   }
  197. }
  198.  
  199.  
  200.  
  201. static void restore_box(Window win, int left, int top, int right, int bottom)
  202. { register int y;
  203.   register VIDEO_PTR p;
  204.   register VIDEO_PTR q;
  205.   register VIDEO_PTR first;
  206.   register VIDEO_PTR last;
  207.   int save_mode;
  208.   int save_col;
  209.   int i;
  210.  
  211.   if(left < 0) left = 0;
  212.   if(top  < 0) top = 0;
  213.   if(right  > DISP_MAX_X) right = DISP_MAX_X;
  214.   if(bottom > DISP_MAX_Y) bottom = DISP_MAX_Y;
  215.  
  216.   save_mode = set_mode(0);
  217.  
  218.   if (win->plane[0])
  219.      save_col = set_color(0);
  220.   else
  221.      save_col = set_color(root_color);
  222.  
  223.  
  224.   // clean area
  225.  
  226.   port_out(8, GRA_I);
  227.   port_out(0xFF, GRA_D);
  228.   first  = VIDEO + LINE_BYTES*top + left/8;
  229.   last   = VIDEO + LINE_BYTES*top + right/8;
  230.   for(y=top; y<=bottom; y++)
  231.   { for(q=first; q<=last; q++) *q = *q;
  232.     first  += LINE_BYTES;
  233.     last   += LINE_BYTES;
  234.    }
  235.  
  236.  
  237.   // fill in plane data
  238.  
  239.   set_mode(2); /* or */
  240.  
  241.   if (win->plane[0])
  242.     for(i = 0; i < 4; i++)
  243.     {
  244.       p = win->plane[i];
  245.   
  246.       set_color(1<<i);
  247.   
  248.       first  = VIDEO + LINE_BYTES*top + left/8;
  249.       last   = VIDEO + LINE_BYTES*top + right/8;
  250.   
  251.       port_out(8, GRA_I);
  252.   
  253.       for(y=top; y<=bottom; y++)
  254.       { for(q=first; q<=last; q++,p++) 
  255.         { port_out(*p, GRA_D);
  256.           *q = *q;
  257.          }
  258.         first  += LINE_BYTES;
  259.         last   += LINE_BYTES;
  260.        }
  261.   
  262.       free((char*)win->plane[i]);
  263.     }
  264.   
  265.     set_mode(save_mode);
  266.     set_color(save_col);
  267. }
  268.  
  269.  
  270.  
  271. static void draw_window(Window win)
  272. {
  273.   int bw  = win->xpos - win->x0 - 2;
  274.   int lw  = win->ypos - win->y0 - 2;
  275.   int bw1 = 2*(bw+1);
  276.  
  277.   int x0 = win->x0;
  278.   int y0 = win->y0;
  279.  
  280.   int x1 = win->x1;
  281.   int y1 = win->y1;
  282.  
  283.   int save_mode = set_mode(0);
  284.  
  285.   set_color(win->bg_col);
  286.   box(root_win,x0,y0,x1,y1);
  287.   set_color(win->label_col);
  288.   box(root_win,x0+bw,y0+bw,x1-bw,y0+lw);
  289.   box(root_win,x0,y0+bw1,x0+bw,y1-bw1);
  290.   box(root_win,x1-bw,y0+bw1,x1,y1-bw1);
  291.   box(root_win,x0+bw1,y1-bw,x1-bw1,y1);
  292.   box(root_win,x0+bw1,y0,x1-bw1,y0+bw);
  293.   set_color(1);
  294.  
  295.   rectangle(root_win,x0,y0,x1,y1);
  296.  
  297.   line(root_win,x0+bw,y0+bw,x0+bw1,y0+bw);
  298.   line(root_win,x0+bw1,y0+bw,x0+bw1,y0+1);
  299.   line(root_win,x0+bw1,y0+1,x1-bw1,y0+1);
  300.   line(root_win,x1-bw1,y0+1,x1-bw1,y0+bw);
  301.   line(root_win,x1-bw1,y0+bw,x1-bw,y0+bw);
  302.   line(root_win,x1-bw,y0+bw,x1-bw,y0+bw1);
  303.   line(root_win,x1-bw,y0+bw1,x1-1,y0+bw1);
  304.   line(root_win,x1-1,y0+bw1,x1-1,y1-bw1);
  305.   line(root_win,x1-1,y1-bw1,x1-bw,y1-bw1);
  306.   line(root_win,x1-bw,y1-bw1,x1-bw,y1-bw);
  307.   line(root_win,x1-bw,y1-bw,x1-bw1,y1-bw);
  308.   line(root_win,x1-bw1,y1-bw,x1-bw1,y1-1);
  309.   line(root_win,x1-bw1,y1-1,x0+bw1,y1-1);
  310.   line(root_win,x0+bw1,y1-1,x0+bw1,y1-bw);
  311.   line(root_win,x0+bw1,y1-bw,x0+bw,y1-bw);
  312.   line(root_win,x0+bw,y1-bw,x0+bw,y1-bw1);
  313.   line(root_win,x0+bw,y1-bw1,x0+1,y1-bw1);
  314.   line(root_win,x0+1,y1-bw1,x0+1,y0+bw1);
  315.   line(root_win,x0+1,y0+bw1,x0+bw,y0+bw1);
  316.   line(root_win,x0+bw,y0+bw1,x0+bw,y0+bw);
  317.  
  318.   rectangle(root_win, win->xpos-1, win->ypos-1,
  319.                       win->xpos+win->width, win->ypos+win->height);
  320.  
  321.   // iconize-button
  322.   set_color(0);
  323.   box(root_win,x0+13,y0+3,x0+27,y0+15);
  324.   set_color(1);
  325.   rectangle(root_win,x0+13,y0+3,x0+27,y0+15);
  326.   line(root_win,x0+14,y0+16,x0+28,y0+16);
  327.   line(root_win,x0+28,y0+4,x0+28,y0+15);
  328.   line(root_win,x0+17,y0+6,x0+23,y0+6);
  329.   line(root_win,x0+16,y0+6,x0+20,y0+13);
  330.   line(root_win,x0+17,y0+6,x0+20,y0+13);
  331.   line(root_win,x0+24,y0+6,x0+20,y0+13);
  332.   line(root_win,x0+23,y0+6,x0+20,y0+13);
  333.  
  334.   set_header(win,win->header);
  335.  
  336.   set_mode(save_mode);
  337.  
  338. }
  339.  
  340.  
  341. Window open_window(int x,int y,int width,int height,const char* header,
  342.                                                     const char* label)
  343.   Window win = new vga_window;
  344.  
  345.   win_top++;
  346.   win_stack[win_top] = win;
  347.  
  348.   strcpy(win->header," ");
  349.   strcpy(win->label,label);
  350.  
  351.   if ( strcmp(label,"PANEL") == 0)
  352.      { win->bg_col = white; // grey
  353.        win->label_col = violet;
  354.       }
  355.   else
  356.      { win->bg_col = white;
  357.        win->label_col = yellow;
  358.       }
  359.  
  360.   width  += 2*BORDER_W;
  361.   height += HEADER_W+BORDER_W;
  362.  
  363.   if (width > DISP_WIDTH) width = DISP_WIDTH;
  364.   if (height > DISP_HEIGHT) height = DISP_HEIGHT;
  365.  
  366.   if (x+width > DISP_WIDTH) x = DISP_WIDTH - width;
  367.   if (x < 0) x = 0;
  368.   if (y+height > DISP_HEIGHT) y = DISP_HEIGHT - height;
  369.   if (y < 0) y = 0;
  370.  
  371.   win->x0 = x;
  372.   win->y0 = y;
  373.   win->x1 = x+width-1;
  374.   win->y1 = y+height-1;
  375.   win->xpos = x+BORDER_W;
  376.   win->ypos = y+HEADER_W;
  377.   win->width = width - 2*BORDER_W; 
  378.   win->height = height - HEADER_W - BORDER_W;
  379.  
  380.   win->iconized = 0;
  381.   win->save_x0 = 3;
  382.   win->save_y0 = 3 + 150*(win_top-1);
  383.   win->save_x1 = win->save_x0 + 128 + 2*BORDER_W;
  384.   win->save_y1 = win->save_y0 + 128 + HEADER_W + BORDER_W;
  385.   win->save_bg_col = white;
  386.  
  387.   save_box(win);
  388.   draw_window(win);
  389.   set_header(win,header);
  390.   return win;
  391. }
  392.  
  393.  
  394. void close_window(Window win)
  395. { win = win_stack[win_top];  /* can close top window only */
  396.   restore_box(win,win->x0,win->y0,win->x1,win->y1);
  397.   win_top--;
  398.   delete win;
  399.  }
  400.  
  401.  
  402.  
  403.  
  404.  
  405. void set_read_gc()
  406. { save_mode = set_mode(1);
  407.   save_ls   = set_line_style(0);
  408.   save_lw   = set_line_width(1);
  409.   set_color(1);
  410.   show_pointer();
  411.  }
  412.  
  413. void reset_gc()
  414. { hide_pointer();
  415.   set_mode(save_mode);
  416.   set_line_style(save_ls);
  417.   set_line_width(save_lw);
  418.  }
  419.  
  420.  
  421. #define UP  72
  422. #define DO  80
  423. #define LE  75
  424. #define RI  77
  425.  
  426. #define F1  59
  427. #define F2  60
  428. #define F3  61
  429. #define F4  62
  430. #define SF1 84
  431. #define SF2 85
  432. #define SF3 86
  433. #define CF1 94
  434. #define CF2 95
  435. #define CF3 96
  436.  
  437. char get_key()
  438. {
  439. #if defined(__GNUG__)
  440.   return getkey();
  441. #else
  442.   return getch();
  443. #endif
  444. }
  445.  
  446.  
  447. static int handle_next_event(Window *win, int *val, int *x, int *y)
  448. {
  449.   int  e =  no_event;
  450.   int  i;
  451.  
  452.   union REGS key_regs;
  453.   union REGS mouse_regs;
  454.  
  455.   if (event_buffer_e != -1)
  456.   { *val = event_buffer_val;
  457.     *win = event_buffer_win;
  458.     *x = mouse_x - (*win)->xpos;
  459.     *y = mouse_y - (*win)->ypos;
  460.     last_event_e = event_buffer_e;
  461.     last_event_val = event_buffer_val;
  462.     last_event_win = event_buffer_win;
  463.     event_buffer_e = -1;
  464.     return last_event_e;
  465.    }
  466.  
  467.   mouse_regs.x.cx = 8*mouse_x;
  468.   mouse_regs.x.dx = 8*mouse_y;
  469.  
  470.  
  471.   if (kbhit())
  472.   { 
  473.     int step = 8;
  474.  
  475.     char c = get_key();
  476.  
  477.     if (c==27) 
  478.     { close_display();
  479.       exit(0);
  480.      }
  481.  
  482.     if (c != 0)   /* ascii char */
  483.        { *val = c;
  484.          e = key_press_event;
  485.         }
  486.     else          /* cursor or function key  */
  487.        { 
  488.          c = get_key();
  489.  
  490.          switch(c) {
  491.  
  492.          case  LE: mouse_regs.x.cx -= step;
  493.                    e = motion_event;
  494.                    break;
  495.  
  496.          case  RI: mouse_regs.x.cx += step;
  497.                    e = motion_event;
  498.                    break;
  499.  
  500.          case  UP: mouse_regs.x.dx -= step;
  501.                    e = motion_event;
  502.                    break;
  503.  
  504.          case  DO: mouse_regs.x.dx += step;
  505.                    e = motion_event;
  506.                    break;
  507.  
  508.          case  F1: *val = 1;
  509.                    e = button_press_event;
  510.                    break;
  511.  
  512.          case  F2: *val = 2;
  513.                    e = button_press_event;
  514.                    break;
  515.  
  516.          case  F3: *val = 3;
  517.                    e = button_press_event;
  518.                    break;
  519.  
  520.          case  F4: *val = 1;
  521.                    e = button_release_event;
  522.                    break;
  523.  
  524.          case SF1: *val = -1;
  525.                    e = button_press_event;
  526.                    break;
  527.  
  528.          case SF2: *val = -2;
  529.                    e = button_press_event;
  530.                    break;
  531.  
  532.          case SF3: *val = -3;
  533.                    e = button_press_event;
  534.                    break;
  535.  
  536.          case CF1: *val = 4;
  537.                    e = button_press_event;
  538.                    break;
  539.  
  540.          case CF2: *val = 5;
  541.                    e = button_press_event;
  542.                    break;
  543.  
  544.          case  CF3: *val = 6;
  545.                    e = button_press_event;
  546.                    break;
  547.         }
  548.  
  549.         /* set cursor position */
  550.         mouse_regs.x.ax=04;
  551.         int86(0x33,&mouse_regs,&mouse_regs);
  552.       }
  553.  
  554.    } /* kbhit */
  555.  
  556.  else
  557.  
  558.   if (mouse_installed)
  559.   { 
  560.     int but;
  561.  
  562.     /* check for button press and release events */
  563.  
  564. //INT 33 - MS MOUSE - RETURN BUTTON PRESS DATA
  565. //    AX = 0005h
  566. //    BX = button
  567. //        0000h left
  568. //        0001h right
  569. //        0002h middle (Mouse Systems/Logitech mouse)
  570. //Return: AX = 1 if button pressed
  571. //      BX = number of times specified button has been pressed since last call
  572. //      CX = column at time specified button was last pressed
  573. //      DX = row at time specified button was last pressed
  574.  
  575. //INT 33 - MS MOUSE - RETURN BUTTON RELEASE DATA
  576. //    AX = 0006h
  577. //    BX = button
  578. //        0000h left
  579. //        0001h right
  580. //        0002h middle (Mouse Systems/Logitech mouse)
  581. //Return: AX = 1 if button released
  582. //      BX = # of times specified button has been released since last call
  583. //      CX = column at time specified button was last released
  584. //      DX = row at time specified button was last released
  585.  
  586.     for(but=0; but < 3; but++)
  587.     { 
  588.       mouse_regs.x.ax=5;
  589.       mouse_regs.x.bx=but;
  590.       int86(0x33,&mouse_regs,&mouse_regs);
  591.  
  592.       if (mouse_regs.x.bx)
  593.       { e = button_press_event;
  594.         break;
  595.        }
  596.  
  597.       mouse_regs.x.ax=6;
  598.       mouse_regs.x.bx=but;
  599.       int86(0x33,&mouse_regs,&mouse_regs);
  600.  
  601.       if (mouse_regs.x.bx)
  602.       { e = button_release_event;
  603.         break;
  604.        }
  605.  
  606.      }
  607.  
  608.  
  609.     if (but < 3) 
  610.     { 
  611.       if (but == 0) *val = 1;   // left
  612.       if (but == 1) *val = 3;   // right
  613.  
  614.       //INT 16 - GET KEYBOARD SHIFT KEY STATES
  615.       //          AH = 0002h
  616.       //  OUTPUT: AL  bit 0    right shift
  617.       //              bit 1    left shift
  618.       //              bit 2    ctrl
  619.       //              bit 3    alt
  620.  
  621.       key_regs.h.ah=0x02;
  622.       int86(0x16,&key_regs,&key_regs);
  623.  
  624.       // ALT key simulates middle button  (two-button mouse)
  625.       if (key_regs.h.al & 8) *val = 2; 
  626.  
  627.       if (key_regs.h.al & 3) *val = -*val;   /* shift */
  628.       if (key_regs.h.al & 4) *val += 3;      /* ctrl  */
  629.      }
  630.  
  631.    // INT 33 MS-MOUSE GET CURSOR POSITION
  632.    mouse_regs.x.ax=03;
  633.    int86(0x33,&mouse_regs,&mouse_regs);
  634.   }
  635.  
  636.   if (mouse_regs.x.cx/8 != mouse_x || mouse_regs.x.dx/8 != mouse_y)
  637.   { if (e==no_event) e = motion_event;
  638.     draw_pointer();
  639.     mouse_y = mouse_regs.x.dx/8;
  640.     mouse_x = mouse_regs.x.cx/8;
  641.     draw_pointer();
  642.    }
  643.  
  644.   for(i = win_top; i >= 0; i--)
  645.   { Window w = win_stack[i];
  646.     if (mouse_x >= w->x0  && mouse_x <= w->x1 &&
  647.         mouse_y >= w->y0  && mouse_y <= w->y1 )  break;
  648.    }
  649.  
  650.   *win = win_stack[i];
  651.   *x = mouse_x - (*win)->xpos;
  652.   *y = mouse_y - (*win)->ypos;
  653.  
  654.   if (e != no_event)
  655.   { last_event_e   = e;
  656.     last_event_val = *val;
  657.     last_event_win = *win;
  658.    }
  659.  
  660.   return e;
  661.  }
  662.  
  663.  
  664. void put_back_event() 
  665. { event_buffer_e   = last_event_e;  
  666.   event_buffer_val = last_event_val; 
  667.   event_buffer_win = last_event_win; 
  668.  }
  669.  
  670. static void change_geometry(Window win, int x0, int y0, int x1, int y1)
  671. {
  672.   if (x0==win->x0 && y0==win->y0 && x1==win->x1 && y1==win->y1) return;
  673.  
  674.   int w = x1-x0+1;
  675.   int h = y1-y0+1;
  676.  
  677.   draw_pointer();
  678.   restore_box(win,win->x0,win->y0,win->x1,win->y1);
  679.  
  680.   win->x0 = x0;
  681.   win->y0 = y0;
  682.   win->x1 = x1;
  683.   win->y1 = y1;
  684.   win->xpos = x0+BORDER_W;
  685.   win->ypos = y0+HEADER_W;
  686.   win->width = w - 2*BORDER_W; 
  687.   win->height = h - HEADER_W - BORDER_W;
  688.  
  689.   save_box(win);
  690.   draw_window(win);
  691.   draw_pointer();
  692. }
  693.  
  694.  
  695. static void iconize(Window win)
  696. { Window w;
  697.   int val,x,y;
  698.   box(root_win,win->x0+14,win->y0+4,win->x0+26,win->y0+14);
  699.   while (handle_next_event(&w,&val,&x,&y) != button_release_event);
  700.   box(root_win,win->x0+14,win->y0+4,win->x0+26,win->y0+14);
  701.  
  702.   int x0 = win->save_x0;
  703.   int y0 = win->save_y0;
  704.   int x1 = win->save_x1;
  705.   int y1 = win->save_y1;
  706.   int bg = win->save_bg_col;
  707.   win->save_x0 = win->x0;
  708.   win->save_y0 = win->y0;
  709.   win->save_x1 = win->x1;
  710.   win->save_y1 = win->y1;
  711.   win->save_bg_col = win->bg_col;
  712.   win->bg_col =  bg;
  713.   change_geometry(win,x0,y0,x1,y1);
  714.   win->iconized = 1-win->iconized;
  715.  
  716.   if (win->iconized) 
  717.      insert_bitmap(win, leda_icon_width, leda_icon_height, leda_icon_bits);
  718.  }
  719.  
  720. static void move_win(Window win, int *x, int *y)
  721. { int xp0 = win->x0;
  722.   int yp0 = win->y0;
  723.   int xp1 = win->x1;
  724.   int yp1 = win->y1;
  725.   int wi  = xp1-xp0+1;
  726.   int he  = yp1-yp0+1;
  727.   int xb  = win->xpos - xp0;
  728.   int yb  = win->ypos - yp0;
  729.   int xc = mouse_x; /* absolute cursor coordinates */
  730.   int yc = mouse_y; 
  731.   int dx = xc-xp0;  /* relative to upper left corner */
  732.   int dy = yc-yp0;
  733.  
  734.   Window w;
  735.   int e,val;
  736.  
  737.   rectangle(root_win,xp0-1,yp0-1,xp1+1,yp1+1);
  738.  
  739.   do { e = handle_next_event(&w,&val,x,y);
  740.       if (mouse_x != xc || mouse_y != yc)
  741.        { int rx0 = mouse_x-dx-1;
  742.          int ry0 = mouse_y-dy-1;
  743.          int rx1 = mouse_x-dx+wi;
  744.          int ry1 = mouse_y-dy+he;
  745.          rectangle(root_win,rx0,ry0,rx1,ry1);
  746.          rectangle(root_win,xc-dx-1,yc-dy-1,xc-dx+wi,yc-dy+he);
  747.          xc = mouse_x;
  748.          yc = mouse_y;
  749.        }
  750.      } while (e != button_release_event);
  751.  
  752.   xc -= dx;
  753.   yc -= dy;
  754.  
  755.   rectangle(root_win,xc-1,yc-1,xc+wi,yc+he);
  756.  
  757.   if (xc < 0) xc = 0;
  758.   if (yc < 0) yc = 0;
  759.   if (xc + wi > DISP_MAX_X) xc = DISP_MAX_X - wi;
  760.   if (yc + he > DISP_MAX_Y) yc = DISP_MAX_Y - he;
  761.  
  762.   if (win_top > 1)  /* move panel */
  763.   { change_geometry(win,xc,yc,xc+wi-1,yc+he-1);
  764.     if (win->iconized) 
  765.        insert_bitmap(win, leda_icon_width, leda_icon_height, leda_icon_bits);
  766.     return;
  767.    }
  768.  
  769.   xc -= xc % 8;
  770.   xc += xp0 % 8;
  771.  
  772.   draw_pointer();
  773.   copy_rect(root_win,xp0,yp0+1,xp0+wi,yp0+he-1,xc,yc+1);
  774.   draw_pointer();
  775.  
  776.   set_mode(0);
  777.   set_color(root_color);
  778.  
  779.   if (xc > xp0) 
  780.      box(root_win,xp0,yp0,xc-1,yp1);
  781.   else
  782.      box(root_win,xc+wi,yp0,xp1,yp1);
  783.  
  784.   if (yc > yp0) 
  785.      box(root_win,xp0,yp0,xp1,yc-1);
  786.   else
  787.      box(root_win,xp0,yc+he,xp1,yp1);
  788.  
  789.   set_color(1);
  790.   rectangle(root_win,xc,yc,xc+wi-1,yc+he-1);
  791.  
  792.   set_mode(1);
  793.  
  794.   win->x0 = xc; 
  795.   win->y0 = yc; 
  796.   win->x1 = xc+wi-1; 
  797.   win->y1 = yc+he-1; 
  798.   win->xpos = xc+xb; 
  799.   win->ypos = yc+yb; 
  800.  
  801. }
  802.  
  803.  
  804. static void resize_win(Window win, int* x, int* y, int pos)
  805. { int xp0 = win->x0;
  806.   int yp0 = win->y0;
  807.   int xp1 = win->x1;
  808.   int yp1 = win->y1;
  809.   int xb  = win->xpos - xp0;
  810.   int yb  = win->ypos - yp0;
  811.   
  812.   int xc  = mouse_x; /* absolute cursor coordinates */
  813.   int yc  = mouse_y;
  814.  
  815.   Window w;
  816.   int e,val,dx,dy;
  817.  
  818.   rectangle(root_win,xp0-1,yp0-1,xp1+1,yp1+1);
  819.  
  820.   switch(pos) {
  821.   
  822.    case 0: dx = xp0-xc;          /* upper left */
  823.            dy = yp0-yc;
  824.            break;
  825.  
  826.    case 1: dx = xp1-xc;          /* upper right */
  827.            dy = yp0-yc;
  828.            break;
  829.  
  830.    case 2: dx = xp1-xc;          /* lower right */
  831.            dy = yp1-yc;
  832.            break;
  833.  
  834.    case 3: dx = xp0-xc;          /* lower left */
  835.            dy = yp1-yc;
  836.            break;
  837.  
  838.    }
  839.  
  840.   do { e = handle_next_event(&w,&val,x,y);
  841.       if (mouse_x != xc || mouse_y != yc)
  842.          { 
  843.            switch(pos) {
  844.  
  845.            case 0: rectangle(root_win,mouse_x+dx-1,mouse_y+dy-1,xp1+1,yp1+1);
  846.                    rectangle(root_win,xc+dx-1,yc+dy-1,xp1+1,yp1+1);
  847.                    break;
  848.            
  849.            case 1: rectangle(root_win,xp0-1,mouse_y+dy-1,mouse_x+dx+1,yp1+1);
  850.                    rectangle(root_win,xp0-1,yc+dy-1,xc+dx+1,yp1+1);
  851.                    break;
  852.  
  853.            case 2: rectangle(root_win,xp0-1,yp0-1,mouse_x+dx+1,mouse_y+dy+1);
  854.                    rectangle(root_win,xp0-1,yp0-1,xc+dx+1,yc+dy+1);
  855.                    break;
  856.               
  857.            case 3: rectangle(root_win,mouse_x+dx-1,yp0-1,xp1+1,mouse_y+dy+1);
  858.                    rectangle(root_win,xc+dx-1,yp0-1,xp1+1,yc+dy+1);
  859.                    break;
  860.            
  861.             }
  862.  
  863.            xc = mouse_x;
  864.            yc = mouse_y;
  865.          }
  866.      } while (e != button_release_event);
  867.  
  868.    xc += dx;
  869.    yc += dy;
  870.  
  871.    switch(pos) {
  872.  
  873.    case 0: win->x0 = xc; 
  874.            win->y0 = yc; 
  875.            break;
  876.                 
  877.    case 1: win->x1 = xc; 
  878.            win->y0 = yc; 
  879.            break;
  880.               
  881.    case 2: win->x1 = xc; 
  882.            win->y1 = yc; 
  883.            break;
  884.  
  885.    case 3: win->x0 = xc; 
  886.            win->y1 = yc; 
  887.            break;
  888.            
  889.    }
  890.  
  891.   win->xpos = win->x0 + xb;
  892.   win->ypos = win->y0 + yb;
  893.   win->width  = win->x1 - win->x0 - 2*xb + 1; 
  894.   win->height = win->y1 - win->y0 - xb - yb + 1; 
  895.  
  896.   rectangle(root_win,win->x0-1,win->y0-1,win->x1+1,win->y1+1);
  897.  
  898.   draw_pointer();
  899.  
  900.   restore_box(win,xp0,yp0,xp1,yp1);
  901.  
  902.   save_box(win);
  903.  
  904.   draw_window(win);
  905.  
  906.   draw_pointer();
  907.  
  908.   *x = win->width;
  909.   *y = win->height;
  910.  
  911. }
  912.  
  913.  
  914. int check_next_event(Window* win, int* val, int* x, int *y, unsigned long* t)
  915. {
  916.   // non-blocking
  917.   
  918.   // a primitive window manager active while searching for next event
  919.  
  920.   int cx[4];
  921.   int cy[4];
  922.   int bw = BORDER_W;
  923.   int lw = HEADER_W;
  924.  
  925.   int e = handle_next_event(win,val,x,y);
  926.  
  927.   int x0 = (*win)->x0;
  928.   int y0 = (*win)->y0;
  929.   int x1 = (*win)->x1;
  930.   int y1 = (*win)->y1;
  931.  
  932.  
  933.   cx[0] = x0;
  934.   cy[0] = y0;
  935.   cx[1] = x1-6;
  936.   cy[1] = y0;
  937.   cx[2] = x1-6;
  938.   cy[2] = y1-6;
  939.   cx[3] = x0;
  940.   cy[3] = y1-6;
  941.  
  942.  
  943.   if ( (x0 <= mouse_x && mouse_x <= x0+bw) 
  944.     || (x1 >= mouse_x && mouse_x >= x1-bw)
  945.     || (y0 <= mouse_y && mouse_y <= y0+lw)
  946.     || (y1 >= mouse_y && mouse_y >= y1-bw))
  947.     {
  948.       // pointer on window boundary: move or resize window
  949.  
  950.      if (*win != win_stack[win_top])  /* only top window can be changed  */
  951.      { set_pointer_shape(0);
  952.        return no_event;
  953.       }
  954.  
  955.      for(int i=0; i<4; i++)
  956.        if ( cy[i] <= mouse_y && mouse_y <= cy[i]+6 &&
  957.             cx[i] <= mouse_x && mouse_x <= cx[i]+6 )
  958.        { set_pointer_shape(1);
  959.          if (e == button_press_event && ! (*win)->iconized) 
  960.          { if ((*win)->iconized)
  961.              e = no_event;
  962.            else
  963.              resize_win(*win,x,y,i);
  964.            e = configure_event;
  965.           }
  966.           return e;
  967.         }
  968.  
  969.     set_pointer_shape(0);
  970.    
  971.     if (x0+13 <= mouse_x && mouse_x <= x0+27 &&
  972.         y0+3  <= mouse_y && mouse_y <= y0+15 && e == button_press_event)
  973.     { iconize(*win);
  974.       return ((*win)->iconized) ? no_event : configure_event;
  975.      }
  976.  
  977.  
  978.     if (e== button_press_event) 
  979.     { move_win(*win,x,y);
  980.       if (win_top==1 || (*win)->iconized)  
  981.          return handle_next_event(win,val,x,y);  
  982.       else
  983.          return configure_event;
  984.      }
  985.  
  986.     e = no_event;
  987.  
  988.   }  // if pointer on window boundary
  989.  
  990.   set_pointer_shape(0);
  991.  
  992.   return e;
  993. }
  994.  
  995.  
  996. int get_next_event(Window* win, int* val, int* x, int *y, unsigned long* t)
  997. { // blocking
  998.   int e = no_event;
  999.   while (e == no_event) e = check_next_event(win,val,x,y,t);
  1000.   return e;
  1001.  }
  1002.  
  1003.  
  1004.  
  1005. void open_display()
  1006. { REGS regs;
  1007.  
  1008.   if (display) return;
  1009.  
  1010.   display = 1;
  1011.  
  1012.   vga_init(1,root_color);
  1013.  
  1014.   //INT 33 - MS MOUSE - RESET DRIVER AND READ STATUS
  1015.   //    AX = 0000h
  1016.   //Return: AX = status
  1017.   //        0000h hardware/driver not installed
  1018.   //        FFFFh hardware/driver installed
  1019.   //        BX = number of buttons
  1020.   //        FFFFh two buttons
  1021.   //        0000h other than two
  1022.   //        0003h Mouse Systems/Logitech mouse
  1023.   regs.x.ax=0x00;
  1024.   int86(0x33,®s,®s);
  1025.   mouse_installed = (regs.x.ax == 0x0ffff);
  1026.   mouse_two_buttons = (regs.x.bx == 0x0ffff);
  1027.  
  1028.   //INT 33 - MS MOUSE - DEFINE HORIZONTAL CURSOR RANGE = 0..DISP_MAX_X
  1029.   regs.x.ax=0x07;
  1030.   regs.x.cx=0;
  1031.   regs.x.dx=8*DISP_MAX_X;
  1032.   int86(0x33,®s,®s);
  1033.  
  1034.   //INT 33 - MS MOUSE - DEFINE VERTICAL CURSOR RANGE = 0..DISP_MAX_Y
  1035.   regs.x.ax=0x08;
  1036.   regs.x.cx=0;
  1037.   regs.x.dx=8*DISP_MAX_Y;
  1038.   int86(0x33,®s,®s);
  1039.  
  1040.   //INT 33 - MS MOUSE - DEFINE MICKEY/PIXEL RATIO = 1
  1041.   regs.x.ax=0x0F;
  1042.   regs.x.cx=1;
  1043.   regs.x.dx=1;
  1044.   int86(0x33,®s,®s);
  1045.  
  1046.   //INT 33 - MS MOUSE - SET CURSOR POSITION
  1047.   mouse_x = DISP_MAX_X/2;
  1048.   mouse_y = DISP_MAX_Y/2;
  1049.   regs.x.cx = 8*mouse_x;
  1050.   regs.x.dx = 8*mouse_y;
  1051.   regs.x.ax=04;
  1052.   int86(0x33,®s,®s);
  1053.  
  1054.   root_win = new vga_window;
  1055.   win_stack[0] = root_win;
  1056.   win_top = 0;
  1057.  
  1058.   root_win->x0 = -1000;
  1059.   root_win->y0 = -1000;
  1060.   root_win->x1 =  1000;
  1061.   root_win->y1 =  1000;
  1062.   root_win->xpos = 0;
  1063.   root_win->ypos = 0;
  1064.   root_win->width = DISP_WIDTH;
  1065.   root_win->height = DISP_HEIGHT;
  1066.   root_win->bg_col = root_color;
  1067.  
  1068.   set_color(root_color);
  1069.   box(root_win,0,0,DISP_MAX_X,DISP_MAX_Y);
  1070.   set_color(black);
  1071.   //insert_bitmap(root_win,w,h,leda_bits);
  1072. }
  1073.  
  1074.  
  1075.  
  1076. void close_display()
  1077. { union REGS regs;
  1078.   vga_init(0,0);
  1079.   regs.h.ah=0x00;
  1080.   regs.h.al=0x02;
  1081.   int86(0x10,®s,®s);
  1082.   delete root_win;
  1083. }
  1084.  
  1085.  
  1086. void put_header(Window win)
  1087. { char str[80];
  1088.   int n = (win->width - 40)/text_width("H");
  1089.   strncpy(str,win->header,n);
  1090.   str[n] = 0;
  1091.   put_ctext(root_win,win->x0 + win->width/2 + 20, win->y0 + 10 ,str,0);
  1092.  }
  1093.  
  1094. void set_header(Window win, const char* s)
  1095. { int save_co = set_color(win->label_col);
  1096.   int save_mo = set_mode(0);
  1097.   put_header(win);
  1098.   if (s != win->header) strcpy(win->header,s);
  1099.   set_color(1);
  1100.   put_header(win);
  1101.   set_color(save_co);
  1102.   set_mode(save_mo);
  1103.  }
  1104.  
  1105.  
  1106. int  display_width() { return DISP_WIDTH; }
  1107. int  display_height(){ return DISP_HEIGHT; }
  1108. int  display_depth() { return DISP_DEPTH; }
  1109.  
  1110. int  window_width(Window win)  { return win->width; }
  1111. int  window_height(Window win) { return win->height; }
  1112. void window_position(Window win,int* x,int* y) { *x = win->x0; *y = win->y0; }
  1113.  
  1114.